# -*- coding: utf-8 -*-
import sys
from PySide6.QtCore import Signal, QTimer, Qt
from PySide6.QtGui import QShortcut, QKeySequence
from PySide6.QtWidgets import QWidget, QMessageBox, QApplication
from loguru import logger

from utils.checksum import hex_string_to_list, get_tcon_checksum, i2c0_get_checksum
from plugins.gWMDE09IICUI_ui import Ui_GWMDE09IICForm


class GWMDE09IICWindow(QWidget, Ui_GWMDE09IICForm):
    """
    DE09的IIC通信
    """
    # 声明带一个字典类型参数的信号
    de09IICSignal = Signal(dict)
    needSend = False
    execDelay = 1500  # ms

    # 调节阻尼设置

    def __init__(self):
        super().__init__()
        # 加载UI
        self.setupUi(self)
        # 连接信号与槽
        self.SignalConnectInit()
        # 创建定时器
        self.TimerInit()
        # 添加快捷键
        self.ShortcutFun()
        # 引入公共程序
        from utils.common import commonProgram
        # 引入配置文件
        self.myConfig = commonProgram.EnableConfigHandler()
        print('TpIntWindow get config Version', self.myConfig.version)
        # 引入可控串口信息窗口
        self.serialPortWin = commonProgram.EnableFt4222(winSignal=self.de09IICSignal,
                                                        RecvFt4222Data=self.RecvFt4222Data)
        # 显示窗口
        # self.serialPortWin.show()

    def CleanupSelf(self):
        """
        清理当前窗口并关闭，由其他其他程序调用
        :return:
        """
        try:
            # 停止并注销定时器
            self.timer_delay.stop()
            self.timer_delay.deleteLater()
            self.timer_exec.stop()
            self.timer_exec.deleteLater()
            self.close()  # 关闭当前窗口
            self.deleteLater()  # 释放子窗口资源
            print("TpIntWindow.__del__.ok")
        except Exception as err:
            print("TpIntWindow.__del__.error", err)

    def SignalConnectInit(self):
        """
        连接来自UI对象的信号与槽
        :return:
        """
        self.checkBoxCycleSend.stateChanged.connect(self.CheckBoxCycleSendFun)
        self.checkBoxInit.stateChanged.connect(self.CheckBoxInitFun)

        self.btnOnceSend.clicked.connect(self.BtnOnceSendFun)

        self.horizontalSliderBacklight.valueChanged.connect(self.HorizontalSliderBacklightValueChangedFun)
        self.horizontalSliderBacklight.sliderReleased.connect(self.HorizontalSliderBacklightSliderReleasedFun)

        self.lineEditBacklight.textChanged.connect(self.LineEditBacklightTextChangedFun)
        self.doubleSpinBoxPercent.valueChanged.connect(self.DoubleSpinBoxPercentValueChangedFun)
        self.comboBoxSendMode.currentTextChanged.connect(self.ComboBoxSendModeTextChangedFun)

    def LineEditBacklightTextChangedFun(self, text):
        num = int(text.replace(' ', ''), 16)
        # self.horizontalSliderBacklight.setValue(num)
        if "MCU" in self.comboBoxSendMode.currentText():
            percentValue = (num / 0xFF) * 100
        elif "TCON" in self.comboBoxSendMode.currentText():
            percentValue = (num / 0xFFFF) * 100
        else:
            percentValue = (num / 0xFFFF) * 100
        # self.doubleSpinBoxPercent.setValue(percentValue)
        self.labelPercent.setText(f"{percentValue:.2f} %")

    def DoubleSpinBoxPercentValueChangedFun(self, value):
        if "MCU" in self.comboBoxSendMode.currentText():
            num = int(value * 0xFF / 100)
        elif "TCON" in self.comboBoxSendMode.currentText():
            num = int(value * 0xFFFF / 100)
        else:
            num = int(value * 0xFFFF / 100)
        # print("Value changed by user interaction", num)
        self.horizontalSliderBacklight.setValue(num)

    def ComboBoxSendModeTextChangedFun(self, text):
        logger.debug(text)
        self.checkBoxInit.setChecked(False)

    def BtnOnceSendFun(self):
        if not self.checkBoxInit.isChecked():
            QMessageBox.warning(self, "需要初始化", f"请 先勾选初始化！！！")
            return None
        slaveAddr = self.lineEditI2cAddr.text().strip()
        if (len(slaveAddr) < 1) or (not ("0x" in slaveAddr)):
            QMessageBox.warning(self, "空数据", f"请输入正确的设备地址！--> {slaveAddr}")
            return None

        send_data = self.plainTextEditIICData.toPlainText().strip()
        if len(send_data) < 1:
            QMessageBox.warning(self, "空数据", f"请输入要发送的内容！--> {send_data}")
            return None
        # hex发送
        input_s = send_data
        send_list = []

        while input_s != '':
            try:
                num = int(input_s[0:2], 16)
            except ValueError:
                # QMessageBox.critical(self, 'wrong data', '请输入十六进制数据，以空格分开!')
                return None
            input_s = input_s[2:].strip()
            send_list.append(num)

        input_s = bytes(send_list)
        i2cData = {
            "slaveAddr": eval(slaveAddr),
            "writeData": input_s,
        }

        logger.debug(eval(slaveAddr))
        logger.debug(input_s)

        dictData = {"data": i2cData, "type": "send_hex", "options": {}}
        self.SendDataHandle(dictData)
        if self.checkBoxAutoIncrease.isChecked():
            self.horizontalSliderBacklight.setValue(self.horizontalSliderBacklight.value() + 1)

    def HorizontalSliderBacklightValueChangedFun(self, sliderValue):
        if "MCU" in self.comboBoxSendMode.currentText():
            hex_str = '{:02X}'.format(sliderValue & 0xFF)
        elif "TCON" in self.comboBoxSendMode.currentText():
            hex_str = '{:02X} {:02X}'.format((sliderValue >> 8) & 0xFF, sliderValue & 0xFF)
        else:
            hex_str = '{:02X} {:02X}'.format((sliderValue >> 8) & 0xFF, sliderValue & 0xFF)
        self.lineEditBacklight.setText(hex_str)

        intListData = hex_string_to_list(f"0A {hex_str}")
        # 调用计算函数并获取校验和
        checkSum = get_tcon_checksum(intListData)
        if "MCU" in self.comboBoxSendMode.currentText():
            dataStr = f"03 01 {hex_str}"
        elif "TCON" in self.comboBoxSendMode.currentText():
            dataStr = f"0A {hex_str} {checkSum:02X}"
            intListData = hex_string_to_list(dataStr)
            # 调用计算函数并获取校验和
            checkSum = i2c0_get_checksum(intListData)
            dataStr = dataStr + f" {checkSum:02X}"
            # logger.debug(intListData)
            # logger.debug(checkSum)
        else:
            dataStr = f"FE 5A A5 90 01 52 00 04 0A {hex_str} {checkSum:02X} 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
            intListData = hex_string_to_list(dataStr)
            # 调用计算函数并获取校验和
            checkSum = i2c0_get_checksum(intListData)
            dataStr = dataStr + f" {checkSum:02X}"
            # logger.debug(intListData)
            # logger.debug(checkSum)
        # logger.debug(dataStr)
        self.plainTextEditIICData.setPlainText(dataStr)
        self.needSend = True

    def HorizontalSliderBacklightSliderReleasedFun(self):
        self.needSend = False
        self.btnOnceSend.click()

    def CheckBoxCycleSendFun(self):
        """
        定时执行
        :return:
        """
        if self.checkBoxCycleSend.isChecked():
            timeDelay = int(self.spinBoxCycleDelay.text())
            if timeDelay < 1:
                QMessageBox.critical(self, 'wrong data', '请输入 正确的 延时 ！')
                self.checkBoxCycleSend.setChecked(False)
                return None
            self.timer_delay.start(timeDelay)
            self.spinBoxCycleDelay.setEnabled(False)
        else:
            self.timer_delay.stop()
            self.spinBoxCycleDelay.setEnabled(True)

    def CheckBoxInitFun(self, state):
        logger.debug(state)
        if state:
            self.horizontalSliderBacklight.setMaximum(0xFFFF)
            if "MCU" in self.comboBoxSendMode.currentText():
                self.horizontalSliderBacklight.setMaximum(0xFF)
                self.plainTextEditIICData.setPlainText("04 01 01")
            elif "TCON" in self.comboBoxSendMode.currentText():
                self.plainTextEditIICData.setPlainText("04 00 04")
            else:
                self.plainTextEditIICData.setPlainText(
                    "FE 5A A5 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 81")
            self.btnOnceSend.click()
        else:
            self.checkBoxInit.setChecked(True)
            if "MCU" in self.comboBoxSendMode.currentText():
                self.plainTextEditIICData.setPlainText("04 01 00")
            elif "TCON" in self.comboBoxSendMode.currentText():
                self.plainTextEditIICData.setPlainText("04 01 05")
            else:
                self.plainTextEditIICData.setPlainText(
                    "FE 5A A5 81 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80")
            self.btnOnceSend.click()
            self.checkBoxInit.setChecked(False)

    def TimerInit(self):
        """
        定时器创建与信号连接
        此处添加了定时器，一定要在 `CleanupSelf`中添加注销操作，否则切换测试项时不会失效，会一直以子线程运行
        :return:
        """
        self.timer_delay = QTimer()
        self.timer_delay.timeout.connect(self.TimeDelayFun)
        self.timer_exec = QTimer()
        self.timer_exec.timeout.connect(self.HandExecFun)
        self.timer_exec.start(self.execDelay)

    def TimeDelayFun(self):
        self.timer_delay.stop()
        if self.checkBoxCycleSend.isChecked():
            self.btnOnceSend.click()
            self.CheckBoxCycleSendFun()

    def HandExecFun(self):
        self.timer_exec.stop()
        if self.needSend:
            self.btnOnceSend.click()
            self.needSend = False
        self.timer_exec.start(self.execDelay)

    def ShortcutFun(self):
        """
        快捷键 F11 全屏
        快捷键 F5 清屏
        :return:
        """
        # 快捷键 F11
        self.screenStatus = 'Normal'
        screenShortcut = QShortcut(QKeySequence(Qt.Key_F11), self)
        screenShortcut.activated.connect(self.WindowSizeFun)
        self.setToolTip('全屏与退出全屏：\n               双击 或者 F11')
        # 快捷键 F5
        # screenShortcut2 = QShortcut(QKeySequence(Qt.Key_F5), self)
        # screenShortcut2.activated.connect(self.CleanFun)

    def WindowSizeFun(self):
        """
        控制窗口尺寸，此处为原大小（最小UI布局）或者全屏
        :return:
        """
        if self.screenStatus == 'Normal':
            self.showFullScreen()
            self.screenStatus = 'FullScreen'
        else:
            self.showNormal()
            self.screenStatus = 'Normal'

    def SendDataHandle(self, dataDict: dict):
        """
        发送信号或数据处理函数
        :param dataDict:
        :return:
        """
        # 发送信号处理
        dataObj = dataDict.get('data', '')
        typeValue = dataDict.get('type', 'null').strip()
        # 本窗口发送数据
        if "send_" in typeValue:
            self.de09IICSignal.emit(dataDict)
        elif "read_" in typeValue:
            self.de09IICSignal.emit(dataDict)
        elif "ctrl_gpio2" in typeValue:
            self.de09IICSignal.emit(dataDict)
        elif "read_gpio" in typeValue:
            self.de09IICSignal.emit(dataDict)
        elif 'TpInt_to_' in typeValue:
            # logger.info("Plugin窗口发往其他窗口的数据：", typeValue, dataObj)
            self.de09IICSignal.emit(dataDict)
        elif typeValue != None:
            logger.info(f"dataObj={dataObj}, typeValue={typeValue}")
        # do something

    def RecvFt4222Data(self, dictData: dict):
        """
        用于接收串口控制窗口发过来的信号或数据
        :param dictData:
        :return:
        """
        self.RecvDataHandle(dictData)

    def RecvDataHandle(self, dataDict: dict):
        """
        处理串口控制窗口发过来的信号或数据
        :param dataDict:
        :return:
        """
        dataObj = dataDict.get('data', None)
        typeValue = dataDict.get('type', 'null').strip()
        optionsDict = dataDict.get('options', {})
        # 收到信号
        if 'TpInt_to_' in typeValue:
            return
        if typeValue == 'status_serial':
            if dataObj == "Serial_Window_Showed":
                pass
            elif dataObj == "Serial_Window_Closed":
                pass
        elif typeValue == 'level_gpio':
            pass
        elif typeValue == 'send_hex':
            pass
        elif typeValue == 'read_hex':
            pass
        elif typeValue == 'rece_protobuf':
            pass
        elif typeValue == 'rece_hex':
            pass
        elif typeValue == 'rece_ascii':
            pass
        elif '_to_TpInt' in typeValue:
            logger.info("收到其他窗口发往Plugin窗口的数据：", typeValue, dataObj)
        # 其他情况
        elif typeValue != None:
            logger.info(f"{typeValue} \t {dataObj}")
        # do something

    def closeEvent(self, event):
        """
        防止误触关闭程序
        :param event:
        :return:
        """
        # 创建一个确认退出的对话框
        reply = QMessageBox.question(
            self, "Confirmation", "Are you sure you want to exit?",
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, QMessageBox.StandardButton.No
        )
        if reply == QMessageBox.StandardButton.Yes:
            self.CleanupSelf()
            # 用户确认退出，关闭应用
            event.accept()
        else:
            event.ignore()


# 程序入口，测试当前插件文件使用
if __name__ == "__main__":
    app = QApplication(sys.argv)
    myWindow = GWMDE09IICWindow()
    myWindow.show()
    sys.exit(app.exec())
